<template>
  <div class="patent-graph-container">
    <div class="graph-header">
      <a-space>
        <a-select
          v-model:value="relationType"
          style="width: 200px"
          @change="handleRelationTypeChange"
          placeholder="选择关联类型"
        >
          <a-select-option value="institution">申请机构关联</a-select-option>
          <a-select-option value="inventor">发明人关联</a-select-option>
        </a-select>
        
        <a-input-search
          v-model:value="searchPatentId"
          placeholder="输入专利ID或名称"
          style="width: 300px"
          @search="handleSearch"
          enterButton="搜索"
        />
        
        <a-button @click="resetGraph">重置</a-button>
      </a-space>
    </div>

    <div class="graph-main">
      <div class="graph-chart" ref="chartContainer">
        <!-- ECharts图表将在这里渲染 -->
      </div>

      <div class="graph-detail" v-if="selectedNodeDetail">
        <a-card title="专利详情" :bordered="false" size="small">
          <template #extra>
            <a-button type="link" size="small" @click="closeDetail">
              <CloseOutlined />
            </a-button>
          </template>
          
          <a-descriptions :column="1" size="small" bordered>
            <a-descriptions-item label="发明名称（中文）">
              {{ selectedNodeDetail.zhName || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="发明名称（源文）">
              {{ selectedNodeDetail.originName || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="申请号">
              {{ selectedNodeDetail.applyId || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="申请日">
              {{ formatDate(selectedNodeDetail.applyDate) }}
            </a-descriptions-item>
            <a-descriptions-item label="申请公布号">
              {{ selectedNodeDetail.applyPublicId || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="申请公布日">
              {{ formatDate(selectedNodeDetail.applyPublicDate) }}
            </a-descriptions-item>
            <a-descriptions-item label="申请机构">
              {{ selectedNodeDetail.applyInstitutionZhName || selectedNodeDetail.applyInstitutionOriginName || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="发明人">
              {{ selectedNodeDetail.inventorZhName || selectedNodeDetail.inventorOriginName || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="IPC分类号">
              {{ selectedNodeDetail.ipcClassId || '-' }}
            </a-descriptions-item>
            <a-descriptions-item label="重要性评分">
              <a-progress
                :percent="Math.round((selectedNodeDetail.importance || 0) * 100)"
                :status="getImportanceStatus(selectedNodeDetail.importance)"
                size="small"
              />
            </a-descriptions-item>
            <a-descriptions-item label="摘要" v-if="selectedNodeDetail.summaryZh || selectedNodeDetail.summary">
              <div class="summary-text">
                {{ selectedNodeDetail.summaryZh || selectedNodeDetail.summary || '-' }}
              </div>
            </a-descriptions-item>
          </a-descriptions>
        </a-card>
      </div>
    </div>

    <!-- 右键菜单 -->
    <div
      v-show="contextMenuVisible"
      class="context-menu"
      :style="{ left: contextMenuPosition.x + 'px', top: contextMenuPosition.y + 'px' }"
      @click.stop
    >
      <a-menu mode="vertical" @click="handleContextMenuClick">
        <a-menu-item key="setCenterNode" v-if="contextMenuNode && contextMenuNode.type === 'patent'">
          <SwapOutlined /> 设为核心节点
        </a-menu-item>
        <a-menu-item key="viewDetail" v-if="contextMenuNode && contextMenuNode.type === 'patent'">
          <FileSearchOutlined /> 查看详情
        </a-menu-item>
        <a-sub-menu key="changeRelation" title="切换关联关系">
          <a-menu-item key="institution">
            <BankOutlined /> 申请机构关联
          </a-menu-item>
          <a-menu-item key="inventor">
            <UserOutlined /> 发明人关联
          </a-menu-item>
        </a-sub-menu>
      </a-menu>
    </div>

    <!-- 专利详情弹窗 -->
    <a-modal
      v-model:visible="detailModalVisible"
      title="专利详情"
      width="80%"
      :footer="null"
      :maskClosable="true"
      destroyOnClose
    >
      <a-descriptions :column="2" bordered v-if="modalNodeDetail">
        <a-descriptions-item label="发明名称（中文）" :span="2">
          {{ modalNodeDetail.zhName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="发明名称（源文）" :span="2">
          {{ modalNodeDetail.originName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="申请号">
          {{ modalNodeDetail.applyId || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="申请日">
          {{ formatDate(modalNodeDetail.applyDate) }}
        </a-descriptions-item>
        <a-descriptions-item label="申请公布号">
          {{ modalNodeDetail.applyPublicId || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="申请公布日">
          {{ formatDate(modalNodeDetail.applyPublicDate) }}
        </a-descriptions-item>
        <a-descriptions-item label="申请机构（中文）" :span="2">
          {{ modalNodeDetail.applyInstitutionZhName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="申请机构（源文）" :span="2">
          {{ modalNodeDetail.applyInstitutionOriginName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="发明人（中文）" :span="2">
          {{ modalNodeDetail.inventorZhName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="发明人（源文）" :span="2">
          {{ modalNodeDetail.inventorOriginName || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="地址" :span="2">
          {{ modalNodeDetail.address || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="IPC分类号" :span="2">
          {{ modalNodeDetail.ipcClassId || '-' }}
        </a-descriptions-item>
        <a-descriptions-item label="重要性评分" :span="2">
          <a-progress
            :percent="Math.round((modalNodeDetail.importance || 0) * 100)"
            :status="getImportanceStatus(modalNodeDetail.importance)"
          />
        </a-descriptions-item>
        <a-descriptions-item label="摘要（中文）" :span="2" v-if="modalNodeDetail.summaryZh">
          <div class="summary-text">{{ modalNodeDetail.summaryZh }}</div>
        </a-descriptions-item>
        <a-descriptions-item label="摘要（源文）" :span="2" v-if="modalNodeDetail.summary">
          <div class="summary-text">{{ modalNodeDetail.summary }}</div>
        </a-descriptions-item>
      </a-descriptions>
    </a-modal>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { message } from 'ant-design-vue';
import * as echarts from 'echarts';
import { getPatentGraphData, getPatentDetail } from './PatentGraph.api';
import { CloseOutlined, SwapOutlined, FileSearchOutlined, BankOutlined, UserOutlined } from '@ant-design/icons-vue';

const chartContainer = ref<HTMLElement>();
let chartInstance: echarts.ECharts | null = null;

const relationType = ref<string>('institution');
const searchPatentId = ref<string>('');
const currentPatentId = ref<string>('');
const selectedNodeDetail = ref<any>(null);
const modalNodeDetail = ref<any>(null);
const detailModalVisible = ref<boolean>(false);

// 右键菜单相关
const contextMenuVisible = ref<boolean>(false);
const contextMenuPosition = ref({ x: 0, y: 0 });
const contextMenuNode = ref<any>(null);

onMounted(() => {
  initChart();
  
  // 添加全局点击事件监听，用于关闭右键菜单
  document.addEventListener('click', closeContextMenu);
  document.addEventListener('contextmenu', closeContextMenu);
  
  // 监听窗口大小变化
  window.addEventListener('resize', handleResize);
});

onBeforeUnmount(() => {
  if (chartInstance) {
    chartInstance.dispose();
    chartInstance = null;
  }
  
  document.removeEventListener('click', closeContextMenu);
  document.removeEventListener('contextmenu', closeContextMenu);
  window.removeEventListener('resize', handleResize);
});

const initChart = () => {
  if (!chartContainer.value) return;
  
  chartInstance = echarts.init(chartContainer.value);
  
  // 配置初始空图表
  const option = {
    title: {
      text: '专利谱系图',
      subtext: '请输入专利ID进行搜索',
      left: 'center',
      top: 'center',
      textStyle: {
        fontSize: 20,
        color: '#999'
      },
      subtextStyle: {
        fontSize: 14,
        color: '#999'
      }
    },
    tooltip: {},
    series: []
  };
  
  chartInstance.setOption(option);
  
  // 绑定点击事件
  chartInstance.on('click', handleNodeClick);
  
  // 绑定右键事件
  chartInstance.getZr().on('contextmenu', handleNodeRightClick);
};

const handleSearch = async () => {
  if (!searchPatentId.value) {
    message.warning('请输入专利ID');
    return;
  }
  
  currentPatentId.value = searchPatentId.value;
  await loadGraphData(currentPatentId.value, relationType.value);
};

const loadGraphData = async (patentId: string, relation: string) => {
  try {
    const response = await getPatentGraphData({ patentId, relationType: relation });
    
    if (response.success && response.result) {
      const graphData = response.result;
      renderGraph(graphData);
      message.success('专利谱系图加载成功');
    } else {
      message.error(response.message || '加载专利谱系图失败');
    }
  } catch (error) {
    console.error('加载专利谱系图失败:', error);
    message.error('加载专利谱系图失败');
  }
};

const renderGraph = (graphData: any) => {
  if (!chartInstance || !graphData) return;
  
  const option = {
    title: {
      text: '专利谱系图',
      subtext: `关联类型: ${relationType.value === 'institution' ? '申请机构' : '发明人'}`,
      left: 'top'
    },
    tooltip: {
      formatter: (params: any) => {
        if (params.dataType === 'node') {
          const node = params.data;
          let html = `<div style="max-width: 300px;">`;
          html += `<strong>${node.name}</strong><br/>`;
          html += `类型: ${getNodeTypeName(node.type)}<br/>`;
          if (node.detail) {
            if (node.detail.importance !== undefined) {
              html += `重要性: ${(node.detail.importance * 100).toFixed(1)}%<br/>`;
            }
            if (node.detail.patentCount !== undefined) {
              html += `专利数量: ${node.detail.patentCount}<br/>`;
            }
          }
          html += `</div>`;
          return html;
        }
        return '';
      }
    },
    legend: [{
      data: graphData.categories.map((c: any) => c.name),
      orient: 'vertical',
      left: 'left',
      top: 'middle'
    }],
    series: [
      {
        type: 'graph',
        layout: 'force',
        data: graphData.nodes.map((node: any) => ({
          ...node,
          symbolSize: Math.max(20, Math.min(80, node.value || 30)),
          label: {
            show: true,
            formatter: (params: any) => {
              const name = params.data.name || '';
              return name.length > 10 ? name.substring(0, 10) + '...' : name;
            }
          },
          itemStyle: {
            color: getNodeColor(node.category, node.importance)
          }
        })),
        links: graphData.links,
        categories: graphData.categories,
        roam: true,
        label: {
          position: 'bottom',
          fontSize: 10
        },
        force: {
          repulsion: 300,
          gravity: 0.1,
          edgeLength: [100, 200],
          layoutAnimation: true
        },
        emphasis: {
          focus: 'adjacency',
          lineStyle: {
            width: 3
          }
        },
        lineStyle: {
          color: 'source',
          curveness: 0.3
        }
      }
    ]
  };
  
  chartInstance.setOption(option, true);
};

const getNodeTypeName = (type: string) => {
  const typeMap: Record<string, string> = {
    'patent': '专利',
    'institution': '申请机构',
    'inventor': '发明人'
  };
  return typeMap[type] || type;
};

const getNodeColor = (category: number, importance?: number) => {
  const colors = [
    '#ff6b6b', // 中心专利 - 红色
    '#4ecdc4', // 申请机构 - 青色
    '#45b7d1', // 发明人 - 蓝色
    '#96ceb4'  // 相关专利 - 绿色
  ];
  
  let color = colors[category] || '#999';
  
  // 根据重要性调整透明度
  if (importance !== undefined && category === 3) {
    const alpha = 0.3 + importance * 0.7;
    color = color + Math.round(alpha * 255).toString(16).padStart(2, '0');
  }
  
  return color;
};

const handleNodeClick = (params: any) => {
  if (params.dataType === 'node') {
    const node = params.data;
    
    // 只有专利节点才显示详情
    if (node.type === 'patent' && node.detail) {
      selectedNodeDetail.value = node.detail;
    } else if (node.detail) {
      // 机构或发明人节点，显示简要信息
      selectedNodeDetail.value = node.detail;
    }
  }
};

const handleNodeRightClick = (event: any) => {
  event.event.preventDefault();
  event.event.stopPropagation();
  
  // 获取点击的节点
  const pointInPixel = [event.offsetX, event.offsetY];
  if (chartInstance) {
    const pointInGrid = chartInstance.convertFromPixel({ seriesIndex: 0 }, pointInPixel);
    
    // 查找最近的节点
    const option: any = chartInstance.getOption();
    if (option && option.series && option.series[0] && option.series[0].data) {
      const nodes = option.series[0].data;
      
      // 简化实现：显示右键菜单
      contextMenuNode.value = nodes.find((n: any) => {
        // 这里应该根据实际位置判断，简化处理
        return true;
      });
      
      contextMenuPosition.value = {
        x: event.event.clientX,
        y: event.event.clientY
      };
      contextMenuVisible.value = true;
    }
  }
};

const handleContextMenuClick = ({ key }: any) => {
  contextMenuVisible.value = false;
  
  if (!contextMenuNode.value) return;
  
  switch (key) {
    case 'setCenterNode':
      // 设为核心节点
      if (contextMenuNode.value.type === 'patent') {
        currentPatentId.value = contextMenuNode.value.id;
        searchPatentId.value = contextMenuNode.value.id;
        loadGraphData(currentPatentId.value, relationType.value);
      }
      break;
    case 'viewDetail':
      // 查看详情
      if (contextMenuNode.value.type === 'patent') {
        showDetailModal(contextMenuNode.value.id);
      }
      break;
    case 'institution':
    case 'inventor':
      // 切换关联关系
      relationType.value = key;
      if (currentPatentId.value) {
        loadGraphData(currentPatentId.value, key);
      }
      break;
  }
};

const showDetailModal = async (patentId: string) => {
  try {
    const response = await getPatentDetail({ patentId });
    if (response.success && response.result) {
      modalNodeDetail.value = response.result;
      detailModalVisible.value = true;
    } else {
      message.error(response.message || '获取专利详情失败');
    }
  } catch (error) {
    console.error('获取专利详情失败:', error);
    message.error('获取专利详情失败');
  }
};

const closeContextMenu = () => {
  contextMenuVisible.value = false;
};

const closeDetail = () => {
  selectedNodeDetail.value = null;
};

const handleRelationTypeChange = () => {
  if (currentPatentId.value) {
    loadGraphData(currentPatentId.value, relationType.value);
  }
};

const resetGraph = () => {
  currentPatentId.value = '';
  searchPatentId.value = '';
  selectedNodeDetail.value = null;
  initChart();
};

const handleResize = () => {
  if (chartInstance) {
    chartInstance.resize();
  }
};

const formatDate = (date: any) => {
  if (!date) return '-';
  const d = new Date(date);
  return d.toLocaleDateString('zh-CN');
};

const getImportanceStatus = (importance?: number) => {
  if (!importance) return 'normal';
  if (importance >= 0.8) return 'success';
  if (importance >= 0.5) return 'normal';
  return 'exception';
};
</script>

<style lang="less" scoped>
.patent-graph-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 16px;
  background: #fff;
  
  .graph-header {
    margin-bottom: 16px;
    padding: 12px;
    background: #f5f5f5;
    border-radius: 4px;
  }
  
  .graph-main {
    flex: 1;
    display: flex;
    gap: 16px;
    min-height: 0;
    
    .graph-chart {
      flex: 1;
      min-width: 0;
      height: 100%;
      border: 1px solid #e8e8e8;
      border-radius: 4px;
    }
    
    .graph-detail {
      width: 400px;
      max-height: 100%;
      overflow-y: auto;
      
      .summary-text {
        max-height: 200px;
        overflow-y: auto;
        line-height: 1.6;
      }
    }
  }
  
  .context-menu {
    position: fixed;
    z-index: 9999;
    background: #fff;
    border: 1px solid #e8e8e8;
    border-radius: 4px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
    
    :deep(.ant-menu) {
      border: none;
    }
  }
}
</style>


